// @Author miaoqing
// @Date 2024/02/22 17:26:00
// @Desc
package logic

import (
	"core/command"
	"core/component/logger"
	"sync"
	"sync/atomic"
)

var (
	cmOnce        sync.Once
	clientManager *ClientManager
)

type ClientManager struct {
	clients        *sync.Map
	players        int32
	userID2Clients *sync.Map
}

func clientManagerGetMe() *ClientManager {
	cmOnce.Do(func() {
		clientManager = &ClientManager{
			clients:        &sync.Map{},
			userID2Clients: &sync.Map{},
		}
	})
	return clientManager
}

// online服务器断线,暂时先断开玩家连接(TODO:后期需要通知玩家切线)
func (mgr *ClientManager) onlineServerDisconnected(srvID, srvAddr string, proIndx uint32) {
	mgr.clients.Range(func(k, v interface{}) bool {
		client, ok := v.(*Client)
		if ok && client.joinOnlineID == srvID {
			if client.userID != 0 {
				logger.Infof("online服务器断线 srvAddr:%v pidx:%v  uid:%v", srvAddr, proIndx, client.userID)
			}
			// 清除连接 关闭连接
			clientManagerGetMe().removeClient(client.ConnID)
			clientManagerGetMe().unbindUserID2Client(client.userID)
			client.userID = 0
			client.Close()
		}
		return true
	})
}

func (mgr *ClientManager) bindUserID2Client(userID uint64, c *Client) {
	_, ok := mgr.userID2Clients.Load(userID)
	if ok {
		logger.Warningf("bind user %v already exist", userID)
	}
	mgr.userID2Clients.Store(userID, c)
}

func (mgr *ClientManager) unbindUserID2Client(userID uint64) {
	mgr.userID2Clients.Delete(userID)
}

func (mgr *ClientManager) getBindUserID2Client(userID uint64) *Client {
	val, ok := mgr.userID2Clients.Load(userID)
	if !ok {
		return nil
	}
	return val.(*Client)
}

func (mgr *ClientManager) sendMsgToClient(userID uint64, data []byte) bool {
	client := mgr.getBindUserID2Client(userID)
	if client == nil {
		return false
	}
	return client.AsyncSendRowMsg(data)
}

func (mgr *ClientManager) addClient(connID int64, c *Client) {
	_, ok := mgr.clients.Load(connID)
	if ok {
		return
	}
	mgr.clients.Store(connID, c)
	atomic.AddInt32(&mgr.players, 1)
}

func (mgr *ClientManager) removeClient(clientID int64) {
	_, ok := mgr.clients.Load(clientID)
	if !ok {
		return
	}
	mgr.clients.Delete(clientID)
	atomic.AddInt32(&mgr.players, -1)

}

func (mgr *ClientManager) clientOnline(msg *command.ClientOnlineRet, srvID string) {
	client := mgr.getBindUserID2Client(msg.UserID)
	if client == nil {
		logger.Errorf("can not found client userID:%v", msg.UserID)
		return
	}
	onlineServer, err := onlineServerMgrGetMe().getEndpoint(srvID)
	if err != nil {
		logger.Error("bind client to conline error:", err)
		return
	}

	client.z = 100
	// client代理消息只需要注册一次
	client.msgRegOnce.Do(func() {
		for _, msgID := range onlineServer.handleMsgs {
			client.registerForwardMsgHandler(msgID, onlineServerMgrGetMe().onlineMsgHandler)
		}
	})

	//// 断线重连-从online来的消息
	//if msg.Reconnection {
	//	client.clientReconnection(msg.Result)
	//	client.isReconnection.Store(false)
	//	return
	//}
	//
	//msgSend := &command.SCPlayerLoginInfo{}
	//	Userid:          msg.Userid,
	//	Moleid:          msg.Charid,
	//	Nick:            msg.Name,
	//	Gold:            msg.Gold,
	//	Sceneid:         msg.Sceneid,
	//	IsNew:           msg.IsNew,
	//	Frame:           msg.Frame,
	//	Head:            msg.Head,
	//	Model:           msg.Model,
	//	Sex:             msg.Sex,
	//	BubbleFrame:     msg.BubbleFrame,
	//	Molecoin:        msg.Molecoin,
	//	Silvecoin:       msg.Silvecoin,
	//	FishingRod:      msg.FishingRod,
	//	Level:           msg.Level,
	//	Exp:             msg.Exp,
	//	RegTime:         msg.RegTime,
	//	ServerTime:      msg.ServerTime,
	//	TodayFirstLogin: msg.TodayFirstLogin,
	//	ProcIndex:       msg.ProcIndex,
	//	Mmid:            msg.Mmid,
	//	Xpanel:          msg.Xpanel,
	//	MoleName:        msg.MoleName,
	//	MoleTag:         msg.MoleTag,
	//	ErrCode:         command.JoinErrorCode_JoinOnlineSucess,
	//	IpRegion:        msg.IpRegion,
	//	JPGoldTick:      msg.JPGoldTick,
	//	VipLv:           msg.VipLv,
	//	PlayerState:     msg.PlayerState,
	//}
	//client.sendMsg(command.Command_SCPlayerLoginInfo_Gateway, msgSend)
	//client.SetProcIndex(msg.ProcIndex)
	//client.SetVirtualProcIndex(msg.VirtualProcIndex)
	logger.Infof("玩家登录上线完成 userID:%v clientAddr:%v", msg.UserID, client.remoteAddr)
}
